﻿using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using SecretLabs.NETMF.Hardware;
using SecretLabs.NETMF.Hardware.Netduino;
using Toolbox.NETMF.Hardware;
using Toolbox.NETMF;
using System.IO;
using System.Collections;

namespace N2Plus_GPS
{
    /// <summary>
    /// Base class required by Netduino
    /// </summary>
    public static class Program
    {
        #region Constants
        /// <summary>
        /// Specify if the Logger module should run
        /// </summary>
        private const bool _Logging = true;
        /// <summary>
        /// Specicy if the Timer module should run
        /// </summary>
        private const bool _Timer = true;

        private const int cnLongDelay = 250;
        private const int cnShortDelay = 50;
        #endregion

        #region Private Variables
        /// <summary>
        /// Stores the Filepath used in the SD Card logging
        /// </summary>
        private static string _GPSLog_Filepath = @"\SD\GPSPosLog";
        /// <summary>
        /// Stores the GPS Track Data used in timing
        /// </summary>
        private static string _GPSTrackData_Filepath = @"\SD\TrackData.csv";
        /// <summary>
        /// Reference to the LCD module to be used through out class
        /// </summary>
        private static Hd44780Lcd _LCD = null;
        /// <summary>
        /// Reference to the GPS module for parsing and receiving data
        /// </summary>
        private static NmeaGps _GPS = null;
        /// <summary>
        /// Reference to the onboard LED incase it is needed for display purposes
        /// </summary>
        private static OutputPort _LED = null;
        /// <summary>
        /// Determine if setup has been completed yet or not
        /// </summary>
        private static bool _SetupComplete = false;
        /// <summary>
        /// Determines if we can log or not, if SD Card Present
        /// </summary>
        private static bool _LoggingPossible = false;
        /// <summary>
        /// Determines if the track gps sectors data was loaded
        /// </summary>
        private static bool _RaceTrackLoaded = false;
        /// <summary>
        /// Stores the loaded RaceTrack information including sectors
        /// </summary>
        private static Racetrack _RaceTrack = null;

        #endregion

        #region Handled Events
        /// <summary>
        /// Handler for when we receive a NMEA String, unparsed by the NmeaGps object
        /// </summary>
        /// <param name="sender">Where this originated from</param>
        /// <param name="NMEAString">Contains the NMEA String</param>
        private static void GPS_evtNMEAStringReceived(object sender, string NMEAString)
        {
            //Write to SD Card
            _LED.Write(true);
            Thread.Sleep(1);
            _LED.Write(false);

            //WriteLog(NMEAString);
        }
        /// <summary>
        /// Event handler for when a position changed has occured
        /// </summary>
        /// <param name="Unused"></param>
        /// <param name="FixType"></param>
        /// <param name="GPSTime"></param>
        private static void GPS_PositionChanged(uint Unused, uint FixType, DateTime GPSTime)
        {
            if (_SetupComplete)
            {
                #region Logging
                //string lvLogEntry = string.Empty;

                //lvLogEntry += _GPS.Latitude.ToString() + ",";
                //lvLogEntry += _GPS.Longitude.ToString() + ",";
                //lvLogEntry += _GPS.Altitude.ToString() + ",";
                //lvLogEntry += _GPS.GPSTime.ToString() + ",";
                //lvLogEntry += _GPS.Kmh.ToString();

                //WriteLog(lvLogEntry);
                #endregion

                #region Laptimer
                if (_Timer)
                {
                    if (_RaceTrackLoaded)
                    {
                        GPSPoint lvCurrentPoint = new GPSPoint();

                        lvCurrentPoint.Latitude = _GPS.Latitude;
                        lvCurrentPoint.Longitude = _GPS.Longitude;

                        bool lvInSector = false;

                        //Calculate laptimes
                        for (int i = 0; i < _RaceTrack.Sectors.Count; i++)
                        {
                            Sector lvSector = (Sector)_RaceTrack.Sectors[i];
                            if (Locator.IsInSectorNew(lvCurrentPoint,lvSector))
                            {
                                lvInSector = true;
                                Debug.Print("Within Sector {" + lvSector.Name + "}");
                                _LCD.ClearDisplay();
                                Thread.Sleep(5);
                                _LCD.WriteLine(0, lvSector.Name);
                                _LCD.WriteLine(1, "KM/H:" + _GPS.Kmh.ToString());
                                _LCD.WriteLine(2, "SAT :" + _GPS.Satellites.ToString());
                                _LCD.WriteLine(3, _GPS.GPSTime.ToString("HH:mm:ss"));
                                Thread.Sleep(cnShortDelay);
                                break;
                            }
                        }

                        #region Debugging
                        if (_GPS.Debugging)
                        {
                            string lvOutput = "";
                            lvOutput += "3D-Fix: " + _GPS.Fix3D.ToString();
                            lvOutput += ", Sattellites: " + _GPS.Satellites.ToString();
                            lvOutput += ", Time: " + _GPS.GPSTime.ToString();
                            lvOutput += ", Latitude: " + _GPS.SLatitude;
                            lvOutput += ", Longitude: " + _GPS.SLongitude;
                            lvOutput += ", Altitude: " + _GPS.SAltitude;
                            lvOutput += ", Knots: " + _GPS.Knots.ToString() + " (" + _GPS.Kmh.ToString() + " km/h)";
                            Debug.Print(lvOutput);

                            // If you want to translate this to a Bing Maps URL, try this:
                            Debug.Print("http://maps.google.co.za/?q=" + Tools.RawUrlEncode(_GPS.Latitude.ToString() + " " + _GPS.Longitude.ToString()));
                        }

                        if (!lvInSector)
                        {
                            //_LCD.ClearDisplay();
                            //Thread.Sleep(5);
                            //_LCD.WriteLine(0, "SAT :" + _GPS.Satellites.ToString());
                            //_LCD.WriteLine(1, "LONG:" + _GPS.Longitude.ToString());
                            //_LCD.WriteLine(2, "LAT :" + _GPS.Latitude.ToString());
                            //_LCD.WriteLine(3, "KM/H:" + _GPS.Kmh.ToString());
                            _LCD.WriteLine(0, "ALT :" + _GPS.Altitude.ToString());
                            _LCD.WriteLine(1, "KM/H:" + _GPS.Kmh.ToString());
                            _LCD.WriteLine(2, "SAT :" + _GPS.Satellites.ToString());
                            _LCD.WriteLine(3, _GPS.GPSTime.ToString("HH:mm:ss"));
                            Thread.Sleep(90);
                        }
                        #endregion
                        
                    }
                }
                #endregion
            }
        }
        /// <summary>
        /// Event handler for when we have sattelites fixture
        /// </summary>
        /// <param name="Unused"></param>
        /// <param name="FixType"></param>
        /// <param name="GPSTime"></param>
        private static void GPS_GotFix(uint Unused, uint FixType, DateTime GPSTime)
        {
            _LCD.ClearDisplay();
            Thread.Sleep(100);
            _LCD.WriteLine(0, "GPS Fixed");
            WriteLog("GPS Fixed");
            Thread.Sleep(1000);
        }
        /// <summary>
        /// Event handler for when we lost GPS signal
        /// </summary>
        /// <param name="Unused"></param>
        /// <param name="FixType"></param>
        /// <param name="GPSTime"></param>
        private static void GPS_LostFix(uint Unused, uint FixType, DateTime GPSTime)
        {
            _LCD.ClearDisplay();
            Thread.Sleep(100);
            _LCD.WriteLine(0, "GPS Lost");
            WriteLog("GPS Lost");
            Thread.Sleep(1000);
        }
        #endregion

        #region Methods

        #region Public
        /// <summary>
        /// Main program entry needed by the Netduino
        /// </summary>
        public static void Main()
        {
            //Call to setup the Netduino
            Setup();

            //Keep program running
            Thread.Sleep(Timeout.Infinite);
        }
        #endregion

        #region Private

        #region Setup
        /// <summary>
        /// Main setup method to call all other setup methods in order
        /// </summary>
        private static void Setup()
        {
            _SetupComplete = false;
            Setup_LCD();
            Setup_SDCard(); 
            Setup_LED();
            Setup_GPS();
            _SetupComplete = true;
        }
        /// <summary>
        /// Setup all the parameters for the LCD Reference
        /// </summary>
        private static void Setup_LCD()
        {
            // Binds all events to the GPS device
            _LCD = new Hd44780Lcd(
                Data4: Pins.GPIO_PIN_D2,
                Data5: Pins.GPIO_PIN_D3,
                Data6: Pins.GPIO_PIN_D4,
                Data7: Pins.GPIO_PIN_D5,
                ClockEnablePin: Pins.GPIO_PIN_D1,
                RegisterSelectPin: Pins.GPIO_PIN_D0,
                ReadWritePin: Cpu.Pin.GPIO_NONE,
                Columns: 20,
                Rows: 4
            );

            _LCD.BlinkPosition = false;

            _LCD.ClearDisplay();
            Thread.Sleep(1000);
        }
        /// <summary>
        /// Setup the SD Card for logging purposes
        /// </summary>
        private static void Setup_SDCard()
        {
            _LCD.ClearDisplay();
            Thread.Sleep(100);

            _LCD.WriteLine(0, "Setup SD Card");

            #region Logging
            if (_Logging)
            {
                _LCD.WriteLine(1, "Check for log file");
                Thread.Sleep(cnLongDelay);

                _GPSLog_Filepath = _GPSLog_Filepath + "-" + DateTime.Now.Date.ToString("yyyyMMdd") + ".csv";

                try
                {
                    _LoggingPossible = true;

                    if (File.Exists(_GPSLog_Filepath))
                    {
                        _LCD.WriteLine(1, "File exists");
                        Thread.Sleep(cnLongDelay);
                    }
                    else
                    {
                        _LCD.WriteLine(1, "Create File");
                        WriteLog("Setup SD Card");
                        Thread.Sleep(cnLongDelay);
                    }
                }
                catch
                {
                    _LCD.WriteLine(1, "Exception Occured");
                    _LCD.WriteLine(2, "Logging Impossible");
                    _LoggingPossible = false;
                    Thread.Sleep(cnLongDelay);
                }
            }
            #endregion

            #region Timer
            if (_Timer)
            {
                _LCD.WriteLine(1, "Check for track");
                Thread.Sleep(cnLongDelay);

                if (File.Exists(_GPSTrackData_Filepath))
                {
                    _LCD.WriteLine(1, "Found Track File");
                    Thread.Sleep(cnLongDelay);
                    LoadSectors();
                }
                else
                {
                    //No Track Data
                    _LCD.WriteLine(1, "No Track File");
                    Thread.Sleep(cnLongDelay);
                    _RaceTrackLoaded = false;
                }

            }
            #endregion

            _LCD.WriteLine(1, "Complete");
            _LCD.WriteLine(2, "");
            Thread.Sleep(cnLongDelay);
        }
        /// <summary>
        /// Setup the LED Reference
        /// </summary>
        private static void Setup_LED()
        {
            _LCD.ClearDisplay();
            Thread.Sleep(100);
            _LCD.WriteLine(0, "Setup LED");
            _LCD.WriteLine(1, "LED -> N2+ Onboard");
            Thread.Sleep(cnLongDelay);

            _LED = new OutputPort(Pins.ONBOARD_LED, false);
            _LCD.WriteLine(1, "LED -> Complete");
            WriteLog("Setup LED Complete");
            Thread.Sleep(cnLongDelay);
        }
        /// <summary>
        /// Setup the GPS Reference and properties
        /// </summary>
        private static void Setup_GPS()
        {
            _LCD.ClearDisplay();
            Thread.Sleep(100);
            _LCD.WriteLine(0, "Setup GPS");
            _LCD.WriteLine(1, "COM3 : Initializing");
            WriteLog("Setting up GPS");
            WriteLog("Using COM3 BaudRate 9600");
            Thread.Sleep(cnLongDelay);

            _GPS = new NmeaGps(SerialPort: "COM3", BaudRate: 9600,TimeZone : 2);
            _LCD.WriteLine(1, "COM3 : Done");
            WriteLog("COM Port setup complete");
            Thread.Sleep(cnLongDelay);

            _GPS.Debugging = true;
            _LCD.WriteLine(1, "Debugging " + (_GPS.Debugging ? "True" : "False"));
            WriteLog("Debugging " + (_GPS.Debugging ? "True" : "False"));
            Thread.Sleep(cnLongDelay);
            
            _LCD.WriteLine(1, "Ready");
            _LCD.WriteLine(2, "");
            Thread.Sleep(cnLongDelay);

            _LCD.WriteLine(1, "Register Events");
            _LCD.WriteLine(2, "GPS Lost");
            _GPS.LostFix += new NativeEventHandler(GPS_LostFix);
            WriteLog("Lost Fix event registered");
            Thread.Sleep(cnLongDelay);

            _LCD.WriteLine(2, "Position Changed");
            _GPS.PositionChanged += new NativeEventHandler(GPS_PositionChanged);
            WriteLog("Position Changed event registered");
            Thread.Sleep(cnLongDelay);

            _LCD.WriteLine(2, "NMEA Msg Received");
            _GPS.evtNMEAStringReceived += GPS_evtNMEAStringReceived;
            WriteLog("NMEA Msg Received event registered");
            Thread.Sleep(cnLongDelay);

            _LCD.WriteLine(2, "GPS Fix");
            WriteLog("Registering events");
            _GPS.GotFix += new NativeEventHandler(GPS_GotFix);
            WriteLog("Got fix event registered");
            Thread.Sleep(cnLongDelay);

            _LCD.WriteLine(1, "Events Registered");
            _LCD.WriteLine(2, "");
            WriteLog("Completed events registration");
            Thread.Sleep(cnLongDelay);

            // Starts the GPS device
            _LCD.WriteLine(1, "Starting GPS");
            WriteLog("Starting GPS");
            Thread.Sleep(cnLongDelay);
            _GPS.Start();

            _LCD.WriteLine(1, "Started GPS");
            WriteLog("Started GPS");


            _LCD.WriteLine(1, "Complete");
            _LCD.WriteLine(2, "");
            WriteLog("GPS Setup Complete");
            Thread.Sleep(cnLongDelay);

            Configure_MT3339_GPS();
            
            _LCD.ClearDisplay();
            Thread.Sleep(5);
            if (!_GPS.Fix)
            {
                _LCD.WriteLine(0, "Waiting for fix");
                WriteLog("Waiting for fix");
            }


        }
        /// <summary>
        /// Setup specific commands for the GPS unit's chipset
        /// </summary>
        private static void Configure_MT3339_GPS()
        {
            _LCD.WriteLine(2, "Sending Commands");
            WriteLog("Sending configuration commands");
            Thread.Sleep(cnLongDelay);

            #region Queries
            //Query FW
            //const string cnQUERY_FIRMWARE = "$PMTK605*31";
            //_LCD.WriteLine(2, "Query Firmware");
            //_GPS.SendCommand(cnQUERY_FIRMWARE);
            #endregion

            #region Module Configuration

            #region Fix Time
            //Fix time
            //const string cnFIX_TIME_1000 = "$PMTK300,1000,0,0,0,0*1C";
            //_LCD.WriteLine(2, "Fix Time 1000");
            //_GPS.SendCommand(cnFIX_TIME_1000);
            #endregion

            #region DGPS
            //DGPS No Source
            //const string cnDGPS_MODE_NO_SOURCE = "$PMTK301,0*2C";
            //_LCD.WriteLine(2, "DGPS NO SOURCE");
            //_GPS.SendCommand(cnDGPS_MODE_NO_SOURCE);
            
            //DGPS RTCM
            //const string cnDGPS_MODE_RTCM = "$PMTK301,1*2D";
            //_LCD.WriteLine(2, "DGPS RTCM");
            //_GPS.SendCommand(cnDGPS_MODE_RTCM);
            
            //DGPS WAAS
            //const string cnDGPS_MODE_WAAS = "$PMTK301,2*2E";
            //_LCD.WriteLine(2, "DGPS WAAS");
            //_GPS.SendCommand(cnDGPS_MODE_WAAS);
            #endregion

            #region SBAS
            //SBAS OFF
            //const string cnSBAS_OFF = "$PMTK313,0*2F";
            //_LCD.WriteLine(2, "SBAS OFF");
            //_GPS.SendCommand(cnSBAS_OFF);

            //SBAS ON
            //const string cnSBAS_ON = "$PMTK313,1*2E";
            //_LCD.WriteLine(2, "SBAS ON");
            //_GPS.SendCommand(cnSBAS_ON);
            #endregion

            #region AIC
            //AIC ON
            //const string cnAIC_ON = "$PMTK286,1*23";
            //_LCD.WriteLine(2, "AIC ON");
            //_GPS.SendCommand(cnAIC_ON);

            //AIC OFF
            //const string cnAIC_OFF = "$PMTK286,0*22";
            //_LCD.WriteLine(2, "AIC OFF");
            //_GPS.SendCommand(cnAIC_OFF);
            #endregion

            #region EASY
            //EASY QUERY;
            //const string cnEASY_QUERY = "$PMTK869,0*29";
            //_LCD.WriteLine(2, "EASY QUERY");
            //_GPS.SendCommand(cnEASY_QUERY);

            //EASY ON
            //const string cnEASY_ON = "$PMTK869,1,1*35";
            //_LCD.WriteLine(2, "EASY ON");
            //_GPS.SendCommand(cnEASY_ON);

            //EASY OFF
            //const string cnEASY_OFF = "$PMTK869,1,0*34";
            //_LCD.WriteLine(2, "EASY OFF");
            //_GPS.SendCommand(cnEASY_OFF);
            #endregion
            
            #endregion

            #region Output Data
            //DATA
            //All Data
            //const string cnOUTPUT_ALL_DATA = "$PMTK314,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0*28";
            //_LCD.WriteLine(2, "Show all GPS data");
            //WriteLog("Sending (Show all data) command");
            //_GPS.SendCommand(cnOUTPUT_ALL_DATA);
            //Thread.Sleep(cnLongDelay);

            //RMC Only
            //const string cnOUTPUT_RMC_ONLY = "$PMTK314,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*29";
            //_LCD.WriteLine(2, "Show RMC Only");
            //WriteLog("Sending (Show RMC Only) command");
            //_GPS.SendCommand(cnOUTPUT_RMC_ONLY);
            //Thread.Sleep(cnLongDelay);

            //RMC and GGA
            const string cnOUTPUT_RMC_and_GGA = "$PMTK314,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*28";
            _LCD.WriteLine(2, "RMC and GGA data");
            WriteLog("Sending (Show RMC and GGA data) command");
            _GPS.SendCommand(cnOUTPUT_RMC_and_GGA);
            Thread.Sleep(cnLongDelay);
            #endregion

            #region Sampling Rate
            //1Hz
            //const string cnUPDATE_RATE_1HZ = "$PMTK220,1000*1F";
            //_LCD.WriteLine(2, "Update Rate 1Hz");
            //WriteLog("Sending (Update Rate 1hz) command");
            //_GPS.SendCommand(cnUPDATE_RATE_1HZ);
            //Thread.Sleep(cnLongDelay);

            //5hz
            //const string cnUPDATE_RATE_5HZ = "$PMTK220,200*2C";
            //_LCD.WriteLine(2, "Update Rate 5Hz");
            //WriteLog("Sending (Update Rate 5hz) command");
            //_GPS.SendCommand(cnUPDATE_RATE_5HZ);
            //Thread.Sleep(cnLongDelay);

            //10Hz
            const string cnUPDATE_RATE_10HZ = "$PMTK220,100*2F";
            _LCD.WriteLine(2, "Update Rate 10Hz");
            WriteLog("Sending (Update Rate 10hz) command");
            _GPS.SendCommand(cnUPDATE_RATE_10HZ);
            Thread.Sleep(cnLongDelay);
            #endregion

            #region Reset
            //Full Reset
            //const string cnFULL_COLD_RESET = "$PMTK104*37";
            //_LCD.WriteLine(2, "Full Cold Reset");
            //_GPS.SendCommand(cnFULL_COLD_RESET);
            //Thread.Sleep(60000);

            //Hot Reset
            //const string cnHOT_RESET = "$PMTK101*32";
            //_LCD.WriteLine(2, "Hot Reset");
            //_GPS.SendCommand(cnHOT_RESET);
            //Thread.Sleep(60000);

            //Warm Reset
            //const string cnWARM_RESET = "$PMTK102*31";
            //_LCD.WriteLine(2, "Warm Reset");
            //_GPS.SendCommand(cnWARM_RESET);
            //Thread.Sleep(60000);

            //Cold Reset
            //const string cnCOLD_RESET = "$PMTK103*30";
            //_LCD.WriteLine(2, "Cold Reset");
            //_GPS.SendCommand(cnCOLD_RESET);
            //Thread.Sleep(60000);
            #endregion

        }

        #endregion

        /// <summary>
        /// Writes to the SD Card
        /// </summary>
        /// <param name="pEntry"></param>
        private static void WriteLog(string pEntry)
        {
            if (_Logging)
            {
                if (_LoggingPossible)
                {
                    try
                    {
                        Debug.Print(pEntry);
                        StreamWriter lvStreamWriter = new StreamWriter(_GPSLog_Filepath, true);
                        lvStreamWriter.WriteLine(pEntry);
                        lvStreamWriter.Flush();
                        lvStreamWriter.Close();
                    }
                    catch
                    {
                        _LoggingPossible = false;
                    }
                }
            }
        }

        /// <summary>
        /// Loads the GPS Area of the track, including the sectors defined
        /// </summary>
        private static void LoadSectors()
        {
            try
            {
                using (FileStream lvFilestream = new FileStream(_GPSTrackData_Filepath, FileMode.Open))
                {
                    StreamReader lvReader = new StreamReader(lvFilestream);

                    _LCD.WriteLine(1, "Setup Race Track");
                    _RaceTrack = new Racetrack();
                    _RaceTrack.Sectors = new ArrayList();
                    Thread.Sleep(cnLongDelay);

                    string lvEntry = lvReader.ReadLine();

                    _LCD.WriteLine(2, "Loading Sectors");
                    while (!lvReader.EndOfStream)
                    {
                        
                        if (lvEntry != null)
                            if (lvEntry.Length == 0) lvEntry = lvReader.ReadLine();

                        if (lvEntry != null)
                        {
                            if (lvEntry.Length > 0)
                            {

                                Sector lvSector = new Sector();

                                //Structure:
                                //Latitude , Longitude x 4
                                //StartFinish
                                GPSPoint lvGPSPoint1 = new GPSPoint();
                                GPSPoint lvGPSPoint2 = new GPSPoint();
                                GPSPoint lvGPSPoint3 = new GPSPoint();
                                GPSPoint lvGPSPoint4 = new GPSPoint();


                                string[] lvValues = lvEntry.Split(',');

                                //Verify array contains sufficient information
                                if (lvValues.Length >= 9)
                                {
                                    lvSector.Name = lvValues[0];
                                    _LCD.WriteLine(3, lvSector.Name);

                                    double lvLatitude = 0;
                                    double lvLongitude = 0;
                                    double.TryParse(lvValues[1], out lvLatitude);
                                    lvGPSPoint1.Latitude = lvLatitude;
                                    double.TryParse(lvValues[2], out lvLongitude);
                                    lvGPSPoint1.Longitude = lvLongitude;

                                    lvLatitude = 0;
                                    lvLongitude = 0;
                                    double.TryParse(lvValues[3], out lvLatitude);
                                    lvGPSPoint2.Latitude = lvLatitude;
                                    double.TryParse(lvValues[4], out lvLongitude);
                                    lvGPSPoint2.Longitude = lvLongitude;

                                    lvLatitude = 0;
                                    lvLongitude = 0;
                                    double.TryParse(lvValues[5], out lvLatitude);
                                    lvGPSPoint3.Latitude = lvLatitude;
                                    double.TryParse(lvValues[6], out lvLongitude);
                                    lvGPSPoint3.Longitude = lvLongitude;

                                    lvLatitude = 0;
                                    lvLongitude = 0;
                                    double.TryParse(lvValues[7], out lvLatitude);
                                    lvGPSPoint4.Latitude = lvLatitude;
                                    double.TryParse(lvValues[8], out lvLongitude);
                                    lvGPSPoint4.Longitude = lvLongitude;

                                    bool lvStartFinish = lvValues[9] == "1";

                                    lvSector.GPSArea = new ArrayList();
                                    lvSector.GPSArea.Add(lvGPSPoint1);
                                    lvSector.GPSArea.Add(lvGPSPoint2);
                                    lvSector.GPSArea.Add(lvGPSPoint3);
                                    lvSector.GPSArea.Add(lvGPSPoint4);
                                    lvSector.StartFinish = lvStartFinish;

                                    _RaceTrack.Sectors.Add(lvSector);

                                    _LCD.WriteLine(3, lvSector.Name);
                                    Thread.Sleep(cnLongDelay);
                                } 
                            }
                            
                        }

                        lvEntry = "";

                    }

                    if (_RaceTrack.Sectors.Count > 0)
                    {
                        _LCD.WriteLine(1, "Race Track Loaded");
                        _LCD.WriteLine(2, "");
                        _LCD.WriteLine(3, "");
                        _RaceTrackLoaded = true;
                    }
                    else
                    {
                        _LCD.WriteLine(1, "Race Track Failed");
                        _LCD.WriteLine(2, "");
                        _LCD.WriteLine(3, "");
                        _RaceTrackLoaded = false;
                    }

                    lvReader.Close();
                }
            }
            catch
            {
            }

        }
        #endregion

        #endregion
    }
}
